package cn.ljy.uem.service.impl;

import cn.hutool.core.map.BiMap;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import cn.ljy.authority.dao.mapper.SysRoleMapper;
import cn.ljy.authority.dao.mapper.SysUserMapper;
import cn.ljy.authority.dao.mapper.SysUserRoleMapper;
import cn.ljy.authority.model.SysRole;
import cn.ljy.authority.model.SysUser;
import cn.ljy.authority.model.SysUserRole;
import cn.ljy.authority.service.SysUserService;
import cn.ljy.common.exception.model.MyExcelException;
import cn.ljy.common.exception.model.MyServiceException;
import cn.ljy.common.exception.model.base.MyRollBackException;
import cn.ljy.common.model.result.ExcelImportResult;
import cn.ljy.common.utils.password.SHA;
import cn.ljy.common.utils.table.ExcelExceptionMessage;
import cn.ljy.common.utils.table.MyHutoolCustomExcelUtil;
import cn.ljy.common.utils.table.MyTableUtil;
import cn.ljy.uem.dao.*;
import cn.ljy.uem.model.*;
import cn.ljy.uem.model.query.SchoolTeacherQuery;
import cn.ljy.uem.model.query.SchoolTeacherQuery;
import cn.ljy.uem.service.SchoolTeacherExcelService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.Sheet;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;

import javax.validation.constraints.NotNull;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 要在一般业务类只上构建的
 */
@Service
@Validated
@Slf4j
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = MyRollBackException.class)
public class ISchoolTeacherExcelService implements SchoolTeacherExcelService {

    // 判断是否超级用户
    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private SchoolTeacherMapper schoolTeacherMapper;

    @Autowired
    private SchoolMajorMapper schoolMajorMapper;

    @Autowired
    private SchoolDepartmentMapper schoolDepartmentMapper;

    @Autowired
    private SchoolPositionMapper schoolPositionMapper;
    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;

    private String sheetName = "教师表格";//要查找的账户子表
    //性别
    private final static HashMap<Integer, String> SEX_MAP = new HashMap<Integer, String>() {
        {
            put(0, "女");
            put(1, "男");
            put(2, "保密");
        }
    };




    //定义表格的行对象，用于处理表格中的bean
    @Data
    private class TeacherRow {
        private Long id;
        private String departmentName;  //部门名称
        private String majorName;                                           //所属专业名称
        private String positionName;                                        //职务名称
        private String teacherNumber;//教师工号
        private String name;//名字
        private String sex;//性别
        private String birth;//出生日期
        private String national;//民族
        private String nativePlace;//籍贯
        private String address;//地址
        private String tel;//电话
        private String identityCard;//身份证号码
        private String intro;//账户描述
        private Date createTime;//创建时间
        private Date updateTime;//最后编辑时间
    }

    //表格标题栏和实体的映射,必须为有序map集合
    private final static HashMap TEACHER_BEAN_MAP = new LinkedHashMap<String, String>() {
        {
            put("id", "用户编号");
            put("departmentName", "部门名称");
            put("majorName", "专业名称");
            put("positionName", "职务名称");
            put("teacherNumber", "教师工号");
            put("name", "名字");
            put("sex", "性别");
            put("birth", "出生日期");
            put("national", "民族");
            put("nativePlace", "籍贯");
            put("address", "地址");
            put("tel", "电话");
            put("identityCard", "身份证号码");
            put("intro", "个人简介");
            put("createTime", "创建时间");
            put("updateTime", "最后编辑时间");
        }
    };

    /**
     * 将user对象转换为要显示的表格行记录
     *
//     * @paramuser       应该是从数据库里面读取出来的对象。如果是新建对象，应该包含必须的属性（sex、status）
     * @param isTemplate 是否是模板。
     * @return
     */
    private TeacherRow convertTeacherRowToExcelRow(SchoolTeacher schoolTeacher, boolean isTemplate) {
        TeacherRow row = null;
        if (schoolTeacher != null) {
            //定义行记录对象
            row = new TeacherRow();
            //属性拷贝,会将相同属性的值拷贝给新对象
            BeanUtils.copyProperties(schoolTeacher, row);
            //设置性别的标签
            row.setSex(SEX_MAP.get(schoolTeacher.getSex()));
        }

        if(isTemplate) {//如果是示例
            //从数据库读取所有部门中文名
            List<String> departmentNames=schoolDepartmentMapper.getAllNames();
            if(departmentNames.size()>0){//默认选择的部门
                row.setDepartmentName(departmentNames.get(0));
            }
            List<String> majorNames=schoolMajorMapper.getMajorName();
            if(majorNames.size()>0){//默认选择的部门
                row.setMajorName(majorNames.get(0));
            }
            List<String> positionNames=schoolPositionMapper.getPositionNames();
            if(positionNames.size()>0){//默认选择的部门
                row.setPositionName(positionNames.get(0));
            }
        } else{
            //设置部门信息
            if(schoolTeacher.getDepartmentId()!=null){//如果部门存在
                SchoolDepartment schoolDepartment = new SchoolDepartment();
                schoolDepartment=schoolDepartmentMapper.findById(schoolTeacher.getDepartmentId());
//                System.out.println("**********************");
//                System.out.println(schoolDepartment.getName());
                schoolTeacher.setSchoolDepartment(schoolDepartment);
                row.setDepartmentName(schoolTeacher.getSchoolDepartment().getName());
            }
            //设置专业信息
            if(schoolTeacher.getMajorId()!=null){//如果部门存在
                SchoolMajor schoolMajor = new SchoolMajor();
                schoolMajor=schoolMajorMapper.findById(schoolTeacher.getMajorId());
//                System.out.println("**********************");
//                System.out.println(schoolMajor.getName());
                schoolTeacher.setSchoolMajor(schoolMajor);
                row.setMajorName(schoolTeacher.getSchoolMajor().getName());
            }
            //设置职务信息
            if(schoolTeacher.getPositionId()!=null){//如果职务存在
                SchoolPosition schoolPosition = new SchoolPosition();
                schoolPosition=schoolPositionMapper.findById(schoolTeacher.getPositionId());
//                System.out.println("**********************");
//                System.out.println(schoolPosition.getName());
                schoolTeacher.setSchoolPosition(schoolPosition);
                row.setPositionName(schoolTeacher.getSchoolPosition().getName());
            }

        }
        return row;
    }

    /**
     * 根据查询条件导出表格数据
     * 1.如果是模板，则输出标题栏加示例；
     * 2.如果不是模板，则根据查询条件输出所有记录
     *
     * @param isTemplate
     * @param schoolTeacherQuery
     * @paramsysUserQuery查询条件
     */
    @Override
    public ExcelWriter exportExcel(boolean isTemplate, SchoolTeacherQuery schoolTeacherQuery) {
        //通过工具类创建writer
        ExcelWriter writer = ExcelUtil.getWriter(true);
        //设置表格全局样式
        MyHutoolCustomExcelUtil.setBaseGlobalStyle(writer);
        //实现第一个sheet内容
        this.writeExportUserSheet(writer,isTemplate,schoolTeacherQuery);
        //添加第二个sheet:性别字典表
        this.writeExportSexSheet(writer);
        //添加第三个sheet:部门表
        this.writeExportDepartmentsSheet(writer);
        //添加第四个sheet:专业表
        this.writeExportMajorsSheet(writer);
        //添加第五个sheet:职务表
        this.writeExportPositionsSheet(writer);

        return writer;
    }


    /**
     * 输出用户列表sheet，默认是第一个sheet
     * 说明：
     * 1.如果是模板，则输出标题栏加示例；
     * 2.如果不是模板，则输出所有记录
     *
     * @param writer
     * @param isTemplate 是否是模板
     */
    private void writeExportUserSheet(ExcelWriter writer, boolean isTemplate,SchoolTeacherQuery schoolTeacherQuery) {
        // 定义用户记录数集合
        List<TeacherRow> rows = new ArrayList<>();
        //自定义账户对象对应的标题别名,因为是LinkedHashMap，此处的keyset返回的是有序的。
        //步骤一：重命名当前工作表名称。
        writer.renameSheet(sheetName);
        //步骤二：设置列宽
        //获取set集合，因为是LinkedHashMap集合，因此转换过来的是有序的set集合
        Set<String> keySet=TEACHER_BEAN_MAP.keySet();
        //转为list集合,用于在后面能够根据键值获取所在的列索引（避免直接操作列索引导致的灵活性不足）
        List<String> keyList=new ArrayList<String>(keySet);
        //设置部门名称列宽
        writer.setColumnWidth(keyList.indexOf("departmentName"),20);
        writer.setColumnWidth(keyList.indexOf("majorName"),20);
        writer.setColumnWidth(keyList.indexOf("positionName"),20);
        writer.setColumnWidth(keyList.indexOf("teacherNumber"),20);
        writer.setColumnWidth(keyList.indexOf("name"),20);
        //设置角色集合列宽
        writer.setColumnWidth(keyList.indexOf("sex"),20);
        writer.setColumnWidth(keyList.indexOf("birth"),20);
        writer.setColumnWidth(keyList.indexOf("national"),20);
        writer.setColumnWidth(keyList.indexOf("nativePlace"),30);
        writer.setColumnWidth(keyList.indexOf("address"),50);
        writer.setColumnWidth(keyList.indexOf("tel"),20);
        writer.setColumnWidth(keyList.indexOf("identityCard"),50);
        writer.setColumnWidth(keyList.indexOf("intro"),20);
        writer.setColumnWidth(keyList.indexOf("createTime"),20);
        writer.setColumnWidth(keyList.indexOf("updateTime"),20);
        //步骤三：设置标题行的别名Map，以便直接通过Model对象生成表格数据，并且能够在model对象有数据时自动生成标题
        writer.setHeaderAlias(TEACHER_BEAN_MAP);
        //步骤四：添加数据行
        //从数据库读取所有部门名
        List<String> departmentNames =schoolDepartmentMapper.getAllNames();
        List<String> positionNames=schoolPositionMapper.getPositionNames();
        List<String> majorNames=schoolMajorMapper.getMajorName();
        if (isTemplate) {//如果是模板，则在数据行添加示例数据
            //定义项目示例
            SchoolTeacher schoolTeacher = new SchoolTeacher();
            schoolTeacher.setTeacherNumber("2222211552");
            schoolTeacher.setName("张三");
            schoolTeacher.setSex(1);
            schoolTeacher.setNational("汉族");
            schoolTeacher.setBirth(new Date());
            schoolTeacher.setNativePlace("广西柳州");
            schoolTeacher.setTel("1877837xxxx");
            schoolTeacher.setAddress("广西柳州市鱼峰区官塘大道文苑路1号");
            schoolTeacher.setIntro("这是一个账户例子，导入时请删除");
            //定义行记录对象,并将对象转换过来
            TeacherRow row = this.convertTeacherRowToExcelRow(schoolTeacher, true);
            //将记录添加到集合
            if(departmentNames.size()>0){//默认选择的部门
                row.setDepartmentName(departmentNames.get(0));
            }
            if(majorNames.size()>0){//默认选择的部门
                row.setMajorName(majorNames.get(0));
            }
            if(positionNames.size()>0){//默认选择的部门
                row.setPositionName(positionNames.get(0));
            }
            rows.add(row);
        } else {//如果不是模板，则在数据行添加数据行记录
            List<SchoolTeacher> schoolTeachers = schoolTeacherMapper.findAll(schoolTeacherQuery);
            for (int i = 0; i < schoolTeachers.size(); i++) {
                SchoolTeacher schoolTeacher = schoolTeachers.get(i);
                //定义行记录对象,并将对象转换过来
                TeacherRow row = this.convertTeacherRowToExcelRow(schoolTeacher, false);
                //将记录添加到集合
                rows.add(row);
            }
        }
        //步骤五：一次性写出内容，使用默认样式，强制输出标题。如果没有额外自定义样式，Hutool工具会自动生成统一的样式。但是如果使用了自定义样式这里就不会变化
        writer.write(rows, true);
//        步骤六：针对特殊单元格进行处理，包括值和特殊样式的处理
        //在数据行范围内为班级列设置部门列表下拉框
//            String[] classArray=classNames.toArray(new String[classNames.size()]);
        String[] departmentArray=departmentNames.toArray(new String[departmentNames.size()]);
        for(int rowIndex=1;rowIndex<=rows.size();rowIndex++){
            writer.addSelect(1,rowIndex,departmentArray);
        }
        //在数据行范围内为专业列设置部门列表下拉框
        String[] majorArray=majorNames.toArray(new String[majorNames.size()]);
        for(int rowIndex=1;rowIndex<=rows.size();rowIndex++){
            writer.addSelect(2,rowIndex,majorArray);
        }
        String[] positionArray=positionNames.toArray(new String[positionNames.size()]);
        for(int rowIndex=1;rowIndex<=rows.size();rowIndex++){
            writer.addSelect(3,rowIndex,positionArray);
        }
        if (isTemplate) {//如果是模板，将第一行样式标为红色，作为示例。必须放在数据都添加后设置才有用。
            // 为第一个单元格赋值，因为采用bean来传值的话，第一个单元格为Long类型，无法进行字符串复制。因此这里手动复制
            writer.writeCellValue(0, 1, "示例：");
            //将原有单元格样式基础上将字体颜色修改为红色（注意看函数说明，这里会保留原有样式）
            CellStyle cellStyle = MyHutoolCustomExcelUtil.createRedCellStyle(writer, HorizontalAlignment.CENTER);
            //设置第一行包含有数据的样式为红色字体样式
            writer.setRowStyleIfHasData(1, cellStyle);
        }
    }
    /**
     * 输出部门sheet
     *
     * @paramwriter
     */
    private void writeExportDepartmentsSheet(ExcelWriter writer){
        //自定义需要读取或写出的Sheet，如果给定的sheet不存在，创建之。
        writer.setSheet("部门字典表（参考）");
        //将字体恢复为原有样式
        //CellStyle cellStyle= MyHutoolCustomExcelUtil.createNormalCellStyle(writer,HorizontalAlignment.CENTER);
        //必须要清掉上一个表设置的HeaderAlias，否则会混用
        writer.clearHeaderAlias();
        writer.addHeaderAlias("id","部门编号");
        writer.addHeaderAlias("name","部门名称");
        //设置班级集合
        List<SchoolDepartment> departments=schoolDepartmentMapper.findAll(null);//查找所有班级
        // 默认的，未添加alias的属性也会写出，如果想只写出加了别名的字段，可以调用此方法排除之
        writer.setOnlyAlias(true);
        // 合并单元格后的标题行，使用默认标题样式
        writer.merge(writer.getHeaderAlias().size()-1, "部门列表");
        // 一次性写出内容，使用默认样式，强制输出标题
        writer.write(departments, true);
   }

    /**
     * 输出专业sheet
     *
     * @paramwriter
     */
    private void writeExportMajorsSheet(ExcelWriter writer){
        //自定义需要读取或写出的Sheet，如果给定的sheet不存在，创建之。
        writer.setSheet("专业字典表（参考）");
        //将字体恢复为原有样式
        //CellStyle cellStyle= MyHutoolCustomExcelUtil.createNormalCellStyle(writer,HorizontalAlignment.CENTER);
        //必须要清掉上一个表设置的HeaderAlias，否则会混用
        writer.clearHeaderAlias();
        writer.addHeaderAlias("id","专业编号");
        writer.addHeaderAlias("name","专业名称");
        //设置班级集合
        List<SchoolMajor> majors=schoolMajorMapper.findAll(null);//查找所有班级
        // 默认的，未添加alias的属性也会写出，如果想只写出加了别名的字段，可以调用此方法排除之
        writer.setOnlyAlias(true);
        // 合并单元格后的标题行，使用默认标题样式
        writer.merge(writer.getHeaderAlias().size()-1, "专业列表");
        // 一次性写出内容，使用默认样式，强制输出标题
        writer.write(majors, true);
    }

    /**
     * 输出职务sheet
     *
     * @paramwriter
     */
    private void writeExportPositionsSheet(ExcelWriter writer){
        //自定义需要读取或写出的Sheet，如果给定的sheet不存在，创建之。
        writer.setSheet("职务字典表（参考）");
        //将字体恢复为原有样式
        //CellStyle cellStyle= MyHutoolCustomExcelUtil.createNormalCellStyle(writer,HorizontalAlignment.CENTER);
        //必须要清掉上一个表设置的HeaderAlias，否则会混用
        writer.clearHeaderAlias();
        writer.addHeaderAlias("id","职务编号");
        writer.addHeaderAlias("name","职务名称");
        //设置班级集合
        List<SchoolPosition> positions=schoolPositionMapper.findAll(null);//查找所有班级
        // 默认的，未添加alias的属性也会写出，如果想只写出加了别名的字段，可以调用此方法排除之
        writer.setOnlyAlias(true);
        // 合并单元格后的标题行，使用默认标题样式
        writer.merge(writer.getHeaderAlias().size()-1, "专业列表");
        // 一次性写出内容，使用默认样式，强制输出标题
        writer.write(positions, true);
    }
    @Data
    private class SexClass{
        private Integer id;
        private String name;
    }
    /**
     * 输出性别sheet
     *
     * @paramwriter
     */
    private void writeExportSexSheet(ExcelWriter writer){
        //自定义需要读取或写出的Sheet，如果给定的sheet不存在，创建之。
        writer.setSheet("性别字典表（参考）");
        //将字体恢复为原有样式
        //CellStyle cellStyle= MyHutoolCustomExcelUtil.createNormalCellStyle(writer,HorizontalAlignment.CENTER);
        //必须要清掉上一个表设置的HeaderAlias，否则会混用
        writer.clearHeaderAlias();
        writer.addHeaderAlias("id","编号");
        writer.addHeaderAlias("name","性别");

        List<SexClass> list = new ArrayList<SexClass>();
        for (Map.Entry<Integer, String> item : SEX_MAP.entrySet()) {
            SexClass sexClass = new SexClass();
            sexClass.setId(item.getKey());
            sexClass.setName(item.getValue());
            list.add(sexClass);
        }

        // 默认的，未添加alias的属性也会写出，如果想只写出加了别名的字段，可以调用此方法排除之
        writer.setOnlyAlias(true);
        // 合并单元格后的标题行，使用默认标题样式
        writer.merge(writer.getHeaderAlias().size()-1, "性别列表");
        // 一次性写出内容，使用默认样式，强制输出标题
        writer.write(list, true);
    }

    /**
     * 导入账户列表
     * 说明：
     * 1.只有root用户能直接导入账户信息
     *
     * @param inputStream   excel文件流
     * @paramSchoolTeacher
     * @return 返回导入结果
     * @paramuser导入文件的对象
     */
    @Override
    public ExcelImportResult addUsersFromExcel(InputStream inputStream, @NotNull(message = "请先登录") SysUser user) {
        ExcelImportResult result=new ExcelImportResult();
        if(sysUserService.isSyperUser(user.getId())){//如果是超级用户
            //读取账户信息
            List<SchoolTeacher> SchoolTeachers=validateAndReadExcel(inputStream);
            //从账户信息中将需要批量插入和批量更新的记录进行归类
            List<SchoolTeacher> newTeachers=new ArrayList<>();//新插入的记录，为了保证插入顺序，并且User重写了equal方法（根据id判断相等），必须使用list
            Set<SchoolTeacher> oldTeachers=new HashSet<>();//需要更新的记录，因为无所谓顺序，所以用set集合

            List<SysUser> newUsers = new ArrayList<>();
            List<SysUser> oldUsers = new ArrayList<>();
            //将要变更的账户角色信息进行处理
            //为其余属性进行处理
            for(SchoolTeacher teacherOfEach:SchoolTeachers){
                if(teacherOfEach.getId()!=null){//如果需要更新的记录
                    oldTeachers.add(teacherOfEach);

                    SysUser oldUser=new SysUser();
                    oldUser.setId(teacherOfEach.getUserId());
                    oldUser.setUsername("T"+teacherOfEach.getTeacherNumber());
//                    oldUser.setPassword(SHA.getResult("123456"));//不更新密码
                    oldUser.setNickName(teacherOfEach.getName());
                    oldUser.setSex(teacherOfEach.getSex());
                    oldUser.setStatus(1);
                    oldUsers.add(oldUser);
                    result.setUpdateNumber(result.getUpdateNumber()+1);
                }else{
                    //设置初始密码为123456
//                    userOfEach.(SHA.getResult("123456"));
                    newTeachers.add(teacherOfEach);
                    SysUser newUser=new SysUser();
//                    newUser.setId(null);
                    newUser.setUsername("T"+teacherOfEach.getTeacherNumber());
                    newUser.setPassword(SHA.getResult("123456"));
                    newUser.setNickName(teacherOfEach.getName());
                    newUser.setSex(teacherOfEach.getSex());
                    newUser.setStatus(1);
                    newUsers.add(newUser);
                    result.setInsertNumber(result.getInsertNumber()+1);
                    //批量插入角色
                }
            }

            sysUserMapper.saveAllIn(newUsers);//账户添加后会返回主键键ID
            sysUserMapper.updateAllIn(oldUsers);
            //循环将教师表 userId 补全
//            newTeachers.forEach(System.out::println);
            for (SchoolTeacher teacher:newTeachers){
                for (SysUser newUserEach:newUsers){
                    if (newUserEach.getUsername().contains("T"+teacher.getTeacherNumber())){//循环账户信息 如果学号相同则将 user表主键ID 设置给教师
//                        System.out.println(newUserEach);
                        teacher.setUserId(newUserEach.getId());
                    }
                }
            }
            List<SysUserRole>  userRolesOfAdd=new ArrayList<>();//定义要批量添加的用户角色关系
            //对新角色进行角色处理，放在这里的原因是此时已经完成数据的添加，获取到了新插入记录的主键，才能进行关系赋予。
            for(SysUser userOfEach:newUsers){
                SysUserRole userRole=new SysUserRole();
                userRole.setSysUser(userOfEach);
                userRole.setSysRole(new SysRole(-12));
                userRolesOfAdd.add(userRole);
            }
            //批量添加账户角色(教师)关系
            sysUserRoleMapper.saveAllIn(userRolesOfAdd);

            //批量插入记录
            schoolTeacherMapper.saveAllIn(newTeachers);
//            System.out.println(newTeachers);
            //批量编辑记录
            schoolTeacherMapper.updateAllIn(oldTeachers);
//            System.out.println(oldTeachers);
        }else{
            throw new AccessDeniedException("只有超级用户才能导入");
        }
        return result;
    }



    /**
     * 验证表中的字段并返回用户集合
     * 说明：用户创建时间、最后编辑时间不导入
     *
     * @param inputStream
     */
    public List<SchoolTeacher> validateAndReadExcel(InputStream inputStream) {
        //创建用户对象集合
        List<SchoolTeacher> SchoolTeachers = new ArrayList<>();
        //创建用户对象集合
        List<SchoolClass> schoolClasses = new ArrayList<>();

        //定义异常集合
        List<ExcelExceptionMessage> excelExceptions = new ArrayList<ExcelExceptionMessage>();
        //获取工作簿对象
        ExcelReader excelReader = ExcelUtil.getReader(inputStream);
        //ExcelReader excelReader = ExcelUtil.getReader(inputStream,"账户列表");
        //获取所有工作表对象
        List<Sheet> sheets = excelReader.getSheets();
        boolean containsSheet = false;//是否包含指定sheet
        for (Sheet sheet : sheets) {//遍历所有工作表
            if (sheet.getSheetName().equals(sheetName)) {// 如果sheet名为指定的名称
                containsSheet = true;
                //根据该工作表重新创建一个ExcelReader对象
                excelReader = new ExcelReader(sheet);
                //首先判断表中的账户名是否存在重复信息
                if (MyTableUtil.validateRepeatColumn(excelReader.readColumn(1, 1, excelReader.getRowCount()))) {
                    throw new MyServiceException("导入失败：表格中的账户名存在重复字段");
                }
//                //首先判断表中的网名是否存在重复信息
//                if (MyTableUtil.validateRepeatColumn(excelReader.readColumn(2, 1, excelReader.getRowCount()))) {
//                    throw new MyServiceException("导入失败：表格中的昵称存在重复字段");
//                }
                //准备录入数据中要多次查找数据库的数据，避免后面遍历时重复查找，提升性能
                List<SchoolDepartment> departments =schoolDepartmentMapper.findAll(null);
                List<SchoolMajor> majors=schoolMajorMapper.findAll(null);
                List<SchoolPosition> positions=schoolPositionMapper.findAll(null);

                //获取set集合，因为是LinkedHashMap集合，因此转换过来的是有序的set集合
                Collection<String> valueSet = TEACHER_BEAN_MAP.values();
                //转为list集合,用于在后面能够根据键获取所在的列索引
                List<String> keyList = new ArrayList<String>(valueSet);
                //读取第二行到最后一行数据
                //List<List<Object>> rows = excelReader.read(1, excelReader.getRowCount());
                List<Map<String, Object>> rows = excelReader.read(0, 1, excelReader.getRowCount());
                //遍历每行的数据
                for (int rowIndex = 0; rowIndex < rows.size(); rowIndex++) {
                    SchoolTeacher SchoolTeacher = new SchoolTeacher();
                    Map<String, Object> row = rows.get(rowIndex);//获取当前行的数据
                    //第1列：账户id。如果id为空，表示该账户是要插入的账户；否则则是要更新相关信息
                    String userIdString = String.valueOf(row.get("用户编号"));
                    //如果id存在则赋值
                    if (StringUtils.hasLength(userIdString)) {
                        try {
                            SchoolTeacher.setId(Long.valueOf(userIdString));
                            //验证id是否在数据库存在，屏蔽无效id。这里用count，提升性能
                            SchoolTeacherQuery SchoolTeacherQuery = new SchoolTeacherQuery();
                            SchoolTeacherQuery.setId(SchoolTeacher.getId());
                            if (schoolTeacherMapper.count(SchoolTeacherQuery) == 0) {
                                excelExceptions.add(new ExcelExceptionMessage(sheet.getSheetName(), rowIndex + 1, keyList.indexOf("用户编号"), userIdString, "用户主键在系统中不存在"));
                            }
                        } catch (NumberFormatException e) {
                            excelExceptions.add(new ExcelExceptionMessage(sheet.getSheetName(), rowIndex + 1, keyList.indexOf("用户编号"), userIdString, "用户主键必须为整数"));
                        }
                    }
                    //第2列:部门名称
                    String DepartmentName=String.valueOf(row.get("部门名称"));
                    if(StringUtils.hasLength(DepartmentName)){
                        boolean exist=false;//默认该部门不存在
                        for(SchoolDepartment schoolDepartment:departments){
                            if(schoolDepartment.getName().equals(DepartmentName)){
                                exist=true;
                                SchoolTeacher.setSchoolDepartment(schoolDepartment);
                                break;
                            }
                        }
                        if(!exist){
                            excelExceptions.add(new ExcelExceptionMessage(sheet.getSheetName(),rowIndex+1,keyList.indexOf("部门名称"),DepartmentName,DepartmentName+"在系统中不存在"));
                        }
                    }
                    //第3列:专业名称
                    String MajorName=String.valueOf(row.get("专业名称"));
                    if(StringUtils.hasLength(MajorName)){
                        boolean exist=false;//默认该专业不存在
                        for(SchoolMajor schoolMajor:majors){
                            if(schoolMajor.getName().equals(MajorName)){
                                exist=true;
                                SchoolTeacher.setSchoolMajor(schoolMajor);
                                break;
                            }
                        }
                        if(!exist){
                            excelExceptions.add(new ExcelExceptionMessage(sheet.getSheetName(),rowIndex+1,keyList.indexOf("专业名称"),MajorName,MajorName+"在系统中不存在"));
                        }
                    }
                    //第4列:职务名称
                    String PositionName=String.valueOf(row.get("职务名称"));
                    if(StringUtils.hasLength(PositionName)){
                        boolean exist=false;//默认该专业不存在
                        for(SchoolPosition schoolPosition:positions){
                            if(schoolPosition.getName().equals(PositionName)){
                                exist=true;
                                SchoolTeacher.setSchoolPosition(schoolPosition);
                                break;
                            }
                        }
                        if(!exist){
                            excelExceptions.add(new ExcelExceptionMessage(sheet.getSheetName(),rowIndex+1,keyList.indexOf("专业名称"),PositionName,PositionName+"在系统中不存在"));
                        }
                    }
                    //第5列：教师工号
                    String TeacherNumber = String.valueOf(row.get("教师工号"));
                    //如果账户名学号则赋值
                    if (StringUtils.hasLength(TeacherNumber)) {
                        SchoolTeacher.setTeacherNumber(TeacherNumber);
                        if (SchoolTeacher.getId()!=null) {//如果不存在说明是要编辑，则要判定是否重名
                            if (schoolTeacherMapper.countByTeacherNumberAndNotId(TeacherNumber, SchoolTeacher.getId()) > 0) {//判断数据库中的账户是否重名
                                excelExceptions.add(new ExcelExceptionMessage(sheet.getSheetName(), rowIndex + 1, keyList.indexOf("教师工号"), TeacherNumber, "学号在系统中重复"));
                            }
                        } else {//如果是要插入账户
                            if (schoolTeacherMapper.countByTeacherNumberAndNotId(TeacherNumber, SchoolTeacher.getId()) > 0) {//判断数据库中的账户是否重名
                                excelExceptions.add(new ExcelExceptionMessage(sheet.getSheetName(), rowIndex + 1, keyList.indexOf("教师工号"), TeacherNumber, "学号在系统中重复"));
                            }
                            if (sysUserMapper.findOneByUsername("S"+TeacherNumber)!= null){
                                excelExceptions.add(new ExcelExceptionMessage(sheet.getSheetName(), rowIndex + 1, keyList.indexOf("教师工号"), TeacherNumber, "该教师账号在系统中重复"));
                            }
                        }
                    } else {
                        excelExceptions.add(new ExcelExceptionMessage(sheet.getSheetName(), rowIndex + 1, keyList.indexOf("教师工号"), TeacherNumber, "学号不能为空"));
                    }
                    //第6列：名字
                    String nickName = String.valueOf(row.get("名字"));
                    //如果账户名存在则赋值
                    if (StringUtils.hasLength(nickName)) {
                        SchoolTeacher.setName(nickName);
//                        if (SchoolTeacher.getId() != null) {//如果不存在说明是要编辑，则要判定是否重名
//                            if (SchoolTeacherMapper.countByNameAndNotId(nickName, SchoolTeacher.getId()) > 0) {//判断数据库中的昵称是否重名
//                                excelExceptions.add(new ExcelExceptionMessage(sheet.getSheetName(), rowIndex + 1, keyList.indexOf("名字"), nickName, "昵称和系统中的重名"));
//                            }
//                        } else {//如果是要插入账户
//                            if (SchoolTeacherMapper.countNickName(nickName) > 0) {//判断数据库中的昵称是否重名
//                                excelExceptions.add(new ExcelExceptionMessage(sheet.getSheetName(), rowIndex + 1, keyList.indexOf("名字"), nickName, "昵称和系统中的重名"));
//                            }
//                        }
                    } else {
                        excelExceptions.add(new ExcelExceptionMessage(sheet.getSheetName(), rowIndex + 1, keyList.indexOf("名字"), nickName, "昵称不能为空"));
                    }
                    //第7列：性别
                    String sexString = String.valueOf(row.get("性别"));
                    if (StringUtils.hasLength(sexString)) {
                        Collection<String> values = SEX_MAP.values();
                        if (values.contains(sexString)) {//如果包含的值一样
                            //使用hutool的工具集合进行map双向查找
                            BiMap<Integer, String> biMap = new BiMap<>(SEX_MAP);
                            SchoolTeacher.setSex(biMap.getKey(sexString));
                        } else {
                            String sexValues = values.stream().map(String::valueOf).collect(Collectors.joining(","));
                            excelExceptions.add(new ExcelExceptionMessage(sheet.getSheetName(), rowIndex + 1, keyList.indexOf("性别"), sexString, "性别的值只能是:" + sexValues));
                        }
                    } else {
                        excelExceptions.add(new ExcelExceptionMessage(sheet.getSheetName(), rowIndex + 1, keyList.indexOf("性别"), sexString, "性别不能为空"));
                    }
                    //第8列：
                    String birth = String.valueOf(row.get("出生日期"));

                    if (StringUtils.hasLength(birth)) {
                        SchoolTeacher.setBirth(new Date(birth));
                    }
                    //第9列：民族
                    String national = String.valueOf(row.get("民族"));

                    if (StringUtils.hasLength(national)) {
                        SchoolTeacher.setNational(national);
                    }
//                    else {
//                        excelExceptions.add(new ExcelExceptionMessage(sheet.getSheetName(), rowIndex + 1, keyList.indexOf("民族"), national, "民族不能为空"));
//                    }
                    //第10列：籍贯
                    String nativePlace = String.valueOf(row.get("籍贯"));

                    if (StringUtils.hasLength(nativePlace)) {
                        SchoolTeacher.setNativePlace(nativePlace);
                    }
//                    else {
//                        excelExceptions.add(new ExcelExceptionMessage(sheet.getSheetName(), rowIndex + 1, keyList.indexOf("籍贯"), nativePlace, "籍贯不能为空"));
//                    }

                    //第11列:地址
                    String address = String.valueOf(row.get("地址"));

                    if (StringUtils.hasLength(address)) {
                                SchoolTeacher.setAddress(address);
                    }
//                    else {
//                        excelExceptions.add(new ExcelExceptionMessage(sheet.getSheetName(), rowIndex + 1, keyList.indexOf("地址"), address, "地址不能为空"));
//                    }
                    //第12列:电话
                    String tel = String.valueOf(row.get("电话"));

                    if (StringUtils.hasLength(tel)) {
                                SchoolTeacher.setTel(tel);

                    } else {
                        excelExceptions.add(new ExcelExceptionMessage(sheet.getSheetName(), rowIndex + 1, keyList.indexOf("电话"), tel, "电话不能为空"));
                    }
//                    writer.setColumnWidth(keyList.indexOf("identityCard"),50);
                    //第13列:身份证号码
                    String identityCard = String.valueOf(row.get("身份证号码"));
                    if (StringUtils.hasLength(identityCard)) {
                        SchoolTeacher.setIdentityCard(identityCard);
                    };
                    //账户描述
                    SchoolTeacher.setIntro(String.valueOf(row.get("个人简介")));
                    //将账户添加进集合
                    SchoolTeachers.add(SchoolTeacher);
                }
            }
        }
        if (!containsSheet) {//如果指定表不存在
            throw new MyServiceException("导入失败：表格中必须有名称为" + sheetName + "的sheet");
        }
        if (excelExceptions.size() > 0) {//如果存在异常
            throw new MyExcelException(excelExceptions);
        }
        return SchoolTeachers;
    }

}
